package service

import (
	"encoding/json"
	"google.golang.org/protobuf/proto"
	"log"
	"src/config"
	global2 "src/global"
	"src/model/ProtoModel"
)

type Message struct {
}

func GetMessage() *Message {
	return &Message{}
}

// 向指定链接推送消息
func (this *Message) SendAll(data []byte) {
	(&Service{}).SendAll(ProtoModel.DataTypeProto_MESSAGE, data)
}

// 向指定链接推送消息
func (this *Message) Send(data []byte, connId string) {
	(&Service{}).Send(ProtoModel.DataTypeProto_MESSAGE, data, connId)
}

// 向指定链接推送消息
func (this *Message) SendNew(data []byte, connId string, tp string) {

	(&Service{}).SendNew(ProtoModel.DataTypeProto_MESSAGE, data, connId, tp)
}

// 向指定链接推送消息
func (this *Message) SendUid(data []byte, uid string) {
	(&Service{}).SendUid(ProtoModel.DataTypeProto_MESSAGE, data, uid)
}

// 向指定链接推送消息
func (this *Message) SendUids(data []byte, uids []string) {
	(&Service{}).SendUids(ProtoModel.DataTypeProto_MESSAGE, data, uids)
}

// 向指定链接推送消息
func (this *Message) SendUidDid(data []byte, uid string, Did string) {
	(&Service{}).SendUidDid(ProtoModel.DataTypeProto_MESSAGE, data, uid, Did)
}

// 向指定链接推送消息
func (this *Message) SendMsgToUidDid(messageProto *ProtoModel.MessageProto, uid string, Did string) {
	data, _ := this.Marshal(messageProto)
	if data == nil {
		// 格式化失败
		return
	}
	(&Service{}).SendUidDid(ProtoModel.DataTypeProto_MESSAGE, data, uid, Did)
}

// 向指定链接推送消息
func (this *Message) SendMsgToConn(messageProto *ProtoModel.MessageProto, connId string) {
	data, msgFmt := this.Marshal(messageProto)
	if data == nil {
		// 格式化失败
		return
	}
	this.SendNew(data, connId, msgFmt)

}
func (this *Message) Marshal(messageProto *ProtoModel.MessageProto) ([]byte, string) {
	msgFmt := config.V().GetString("client.msg-fmt")
	if messageProto.Action == "" {
		messageProto.Action = "msg"
	}

	if msgFmt == "proto" {
		res, err := proto.Marshal(messageProto)
		if err != nil {
			// 格式化失败
			log.Println(err)
			return nil, msgFmt
		}
		return res, msgFmt
	} else {
		// 转json
		res, err := json.Marshal(messageProto)
		//fmt.Println("data.Unmarshal:", string(res))
		//messageProto.String()
		if err != nil {
			// 格式化失败
			log.Println(err)
			return nil, msgFmt
		}
		return res, msgFmt
	}

}

// 向所有登录用户广播消息

func (this *Message) SendMsgToUsers(messageProto *ProtoModel.MessageProto, uids []string) {
	data, _ := this.Marshal(messageProto)
	if data == nil {
		// 格式化失败
		return
	}
	this.SendUids(data, uids)
}

// 向所有登录用户广播消息
func (this *Message) SendMsgToAll(messageProto *ProtoModel.MessageProto) {
	data, msgFmt := this.Marshal(messageProto)
	if data == nil {
		// 格式化失败
		log.Println(msgFmt)
		return
	}
	this.SendAll(data)
}

// 向指定多个连接推送消息
func (this *Message) SendMsgToUsersConns(messageProto *ProtoModel.MessageProto, conns []string) {
	for _, conn := range conns {
		this.SendMsgToConn(messageProto, conn)
	}
}

// 遍历每条消息发送个所有人
func (this *Message) SendMsgArrToAll(msgArr []*ProtoModel.MessageProto) {
	for _, messageProto := range msgArr {
		this.SendMsgToAll(messageProto)
	}
}

// 遍历每条消息发送给接收人
func (this *Message) SendMsgArrToUserAll(msgArr []*ProtoModel.MessageProto) {
	for _, messageProto := range msgArr {
		this.SendMsgToUser(messageProto, messageProto.Receiver)
	}
}

// 向指定登录用户发送多个消息
func (this *Message) SendMsgArrToUsers(msgArr []*ProtoModel.MessageProto, uids []string) {
	for _, messageProto := range msgArr {
		this.SendMsgToUsers(messageProto, uids)
	}
}

// 向指定登录用户发送多个消息
func (this *Message) SendMsgArrToUser(msgArr []*ProtoModel.MessageProto, uid string) {
	for _, messageProto := range msgArr {
		this.SendMsgToUser(messageProto, uid)
	}
}

// 向指定登录用户下某个设备发送消息
func (this *Message) SendMsgToFd(msg *ProtoModel.MessageProto, Cid string) {

	this.SendMsgToConn(msg, Cid)
}

// 向指定登录用户下某个设备发送消息
func (this *Message) SendMsgArrToFd(msgArr []*ProtoModel.MessageProto, Did string) {
	for _, messageProto := range msgArr {
		this.SendMsgToFd(messageProto, Did)
	}
}

// 向指定登录用户下某个设备发送消息
func (this *Message) SendMsgArrToUserFd(msgArr []*ProtoModel.MessageProto, uid string, Did string) {
	for _, messageProto := range msgArr {
		this.SendMsgToUidDid(messageProto, uid, Did)
	}
}

// 向指定房间发送消息 uid 升级成房间编号。
func (this *Message) SendMsgListToRoom(msgArr []*ProtoModel.MessageProto, roomNo string) {
	for _, messageProto := range msgArr {
		this.SendMsgToRoom(messageProto, roomNo)
	}
}

// 向指定房间发送消息 uid 升级成房间编号。
func (this *Message) SendMsgToRoom(messageProto *ProtoModel.MessageProto, roomNo string) {
	if messageProto.Action == "" {
		messageProto.Action = "room_msg"
	}
	//发给房间内指定接收人
	if messageProto.Receiver != "" {
		this.SendMsgToUser(messageProto, messageProto.Receiver)
	} else {
		//发给房间内所有用户
		userConnWs := global2.Ws_.GetRoomListVal(roomNo)
		if userConnWs != nil {
			for conn, _ := range userConnWs {
				this.SendMsgToConn(messageProto, conn)
			}
		}
		userConnTcp := global2.Tcp_.GetRoomListVal(roomNo)
		if userConnTcp != nil {
			for conn, _ := range userConnTcp {

				this.SendMsgToConn(messageProto, conn)

			}
		}
	}
}

// 向指定登录用户发送消息
func (this *Message) SendMsgToUser(messageProto *ProtoModel.MessageProto, uid string) {
	userConnWs := global2.Ws_.GetUserListVal(uid)
	for _, conn := range userConnWs {
		this.SendMsgToConn(messageProto, conn)
	}
	userConnTcp := global2.Tcp_.GetUserListVal(uid)
	for _, conn := range userConnTcp {
		this.SendMsgToConn(messageProto, conn)
	}
}
